//
//  AccountManager.swift
//  HinsLive
//
//  Created by haoxian on 2019/4/21.
//  Copyright © 2019 Hins. All rights reserved.
//

import Foundation
import SVProgressHUD


final class AccountManager {
    static let share = AccountManager()
    
    static let kUserAccountKey = "kUserAccountKey"
    
    private let userInfoPath: String
    
    private let userInfoUrl: URL
    
    private var _user: UserInfo?
    
    private let vistor: UserInfo
    
    private let lock = NSRecursiveLock()
    
    var isLogin: Bool { return _user != nil }
    
    var user: UserInfo { return _user ?? vistor }
    
    private init() {
        userInfoPath = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! as NSString).appendingPathComponent("userInfo".md5)
        userInfoUrl = URL(string: "file://" + userInfoPath)!
        guard let did = UIDevice.current.identifierForVendor?.uuidString.split(separator: "-").first else { fatalError() }
        vistor = UserInfo.with {
            $0.name = "游客" + did
            $0.uid = String(did)
        }
    }
    
    func load() {
        guard FileManager.default.fileExists(atPath: userInfoPath),
            let data = try? Data(contentsOf: userInfoUrl),
            let user = try? UserInfo(serializedData: data) else { return }
        _user = user
    }
    
    func login(with user: UserInfo) {
        _login(with: user)
        notifiyUpateUserInfo()
    }
    
    func logout() {
        _logout()
        notifiyUpateUserInfo()
    }
    
    func changeUserInfo(_ user: UserInfo) {
        if _changeUserInfo(user) {
            notifiyUpateUserInfo()
        }
    }
}

private extension AccountManager {
    func updateUserInfo(_ user: UserInfo) {
        lock.lock(); defer { lock.unlock() }
        _user = user
        DispatchQueue.filemanager.async {
            do {
                if FileManager.default.fileExists(atPath: self.userInfoPath) {
                    try FileManager.default.removeItem(at: self.userInfoUrl)
                }
                let data = try user.serializedData()
                try data.write(to: self.userInfoUrl)
            } catch {
                SVProgressHUD.showDebugMsg(error.localizedDescription)
            }
        }
    }
    
    func notifiyUpateUserInfo() {
        NotificationCenter.default.post(name: .userStateDidChange, object: nil)
    }
    
    func _login(with user: UserInfo) {
        updateUserInfo(user)
        DispatchQueue.userDefaults.async {
            UserDefaults.standard.set(user.account, forKey: AccountManager.kUserAccountKey)
            UserDefaults.standard.synchronize()
        }
    }
    
    
    func _logout() {
        lock.lock(); defer { lock.unlock() }
        _user = nil
        DispatchQueue.filemanager.async {
            do {
                if FileManager.default.fileExists(atPath: self.userInfoPath) {
                    try FileManager.default.removeItem(at: self.userInfoUrl)
                }
            } catch {
                SVProgressHUD.showDebugMsg(error.localizedDescription)
            }
        }
    }
    
    func _changeUserInfo(_ user: UserInfo) -> Bool {
        lock.lock(); defer { lock.unlock() }
        if isLogin {
            updateUserInfo(user)
        }
        return isLogin
    }
}

